package main

import (
	"database/sql"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"strconv"

	"test.com/fusion"
	"test.com/worlddb"
)

type CharPrototype struct {
	CharName string                 `json:"charName"`
	CharDesc string                 `json:"charDesc"`
	CharInfo *worlddb.CharPrototype `json:"charInfo"`
}

type charWebPrototype struct {
	CharPrototype
}

func handleGetCharDialogArgs(w http.ResponseWriter, r *http.Request) {
	scriptFiles, err := getAllScriptable(worldDB)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	lsRows, err := getAllLoot4DialogTable(worldDB)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	dialogArgs := map[string]interface{}{
		"scriptFiles": scriptFiles,
		"lsRows":      lsRows,
	}
	jsonData, err := json.Marshal(dialogArgs)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetCharEnumType(w http.ResponseWriter, r *http.Request) {
	enumTypes := map[string]interface{}{
		"ScriptType": getEnumScriptType(),
	}
	jsonData, err := json.Marshal(enumTypes)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetCharUIView(w http.ResponseWriter, r *http.Request) {
	uiViews := map[string]interface{}{
		"CharRaceType":  getViewCharRaceType(),
		"CharEliteType": getViewCharEliteType(),
	}
	jsonData, err := json.Marshal(uiViews)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, jsonData)
}

func handleGetCharTreeView(w http.ResponseWriter, r *http.Request) {
	handleGetEditorTreeView(
		w, r, worlddb.EditorTreeView_Type_Char, getAllCharNames)
}

func handleSaveCharTreeView(w http.ResponseWriter, r *http.Request) {
	handleSaveEditorTreeView(w, r, worlddb.EditorTreeView_Type_Char)
}

func handleGetCharInstance(w http.ResponseWriter, r *http.Request) {
	charTypeId, err := strconv.ParseUint(r.FormValue("CharTypeId"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	charData, err := getCharInstanceJsonData(worldDB, uint32(charTypeId))
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, charData)
}

func handleNewCharInstance(w http.ResponseWriter, r *http.Request) {
	charName, charDesc := r.FormValue("CharName"), r.FormValue("CharDesc")
	if charName == "" {
		http.Error(w, "empty character name.", http.StatusBadRequest)
		return
	}
	var charTypeId uint32
	err := fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) (err error) {
		charTypeId, err = newCharInstance(tx, charName, charDesc)
		return
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	charData, err := getCharInstanceJsonData(worldDB, charTypeId)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, charData)
}

func handleCopyCharInstance(w http.ResponseWriter, r *http.Request) {
	charTypeId, err := strconv.ParseUint(r.FormValue("CharTypeId"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var ID uint32
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) (err error) {
		ID, err = copyCharInstance(worldDB, tx, uint32(charTypeId))
		return
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	charData, err := getCharInstanceJsonData(worldDB, ID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeJsonResponseData(w, charData)
}

func handleDeleteCharInstance(w http.ResponseWriter, r *http.Request) {
	charTypeId, err := strconv.ParseUint(r.FormValue("CharTypeId"), 0, 32)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) error {
		return deleteCharInstance(tx, uint32(charTypeId))
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeOKResponseData(w)
}

func handleSaveCharInstance(w http.ResponseWriter, r *http.Request) {
	charData, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	var charProto CharPrototype
	if err = json.Unmarshal(charData, &charProto); err != nil {
		http.Error(w, err.Error(), http.StatusNotAcceptable)
		return
	}
	err = fusion.RunDBTransaction(worldDB, func(tx *sql.Tx) error {
		return saveCharInstance(tx, &charProto)
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	writeOKResponseData(w)
}
